﻿// HSS.Interlink.UI.Converters.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.html)
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2012
// ----------------------------------------------------------------------------
// File:       Converters.cs
// Author:     HSS\gbanta
// Created:    07/16/2011
// Modified:   07/22/2011
// ----------------------------------------------------------------------------
namespace HSS.Interlink.UI
{
	#region Using Directives
	using System;
	using System.Globalization;
	using System.Windows.Data;
	#endregion

	#region VisibilityConverter
	/// <summary>
	/// A type converter for visibility and boolean values.
	/// </summary>
	public class VisibilityConverter : System.Windows.Data.IValueConverter
	{
		/// <summary>
		/// Converts a boolean value to a Visibility value.
		/// </summary>
		/// <param name="value"></param>
		/// <param name="targetType"></param>
		/// <param name="parameter"></param>
		/// <param name="culture"></param>
		/// <returns></returns>
		public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
		{
			if (null != value && value is bool)
			{
				bool visibility = (bool)value;
				return visibility ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
			}
			return System.Windows.Visibility.Visible;
		}
		/// <summary>
		/// Converts a Visibility value to a boolean value.
		/// </summary>
		/// <param name="value"></param>
		/// <param name="targetType"></param>
		/// <param name="parameter"></param>
		/// <param name="culture"></param>
		/// <returns></returns>
		public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
		{
			if (null != value && value is System.Windows.Visibility)
			{
				var visibility = (System.Windows.Visibility)value;
				return (visibility == System.Windows.Visibility.Visible);
			}
			return true;
		}
	}
	#endregion

	#region ByteConverter
	/// <summary>
	/// ByteConverter converts byte (double) values, in to a friendly such as 10KB or 500 bytes
	/// </summary>
	public class ByteConverter : IValueConverter
	{
		#region IValueConverter Members
		/// <summary>
		/// Convert byte values to String Representation as byte, kb or gb
		/// </summary>
		/// <param name="value">The value to convert</param>
		/// <param name="targetType">The destination type</param>
		/// <param name="parameter">Optional and unused parameter</param>
		/// <param name="culture">Curernt Thread Culture</param>
		/// <returns>A string contains the size and size indicator as a string</returns>
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			var size = "0 KB";
			if (value != null)
				return CovertToString(System.Convert.ToDouble(value, System.Globalization.CultureInfo.InvariantCulture));
			return size;
		}
		/// <summary>
		/// We only use one-way binding, so we don't implement this.
		/// </summary>
		/// <param name="value"></param>
		/// <param name="targetType"></param>
		/// <param name="parameter"></param>
		/// <param name="culture"></param>
		/// <returns></returns>
		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			throw new NotImplementedException();
		}
		#endregion

		internal static string CovertToString(double bytes)
		{
			const int scale = 1024;
			var orders = new string[] { "GB", "MB", "KB", "Bytes" };
			var max = (long)Math.Pow(scale, orders.Length - 1);

			foreach (string order in orders)
			{
				if (bytes > max)
				{
					if (bytes <= Math.Pow(scale, 2))
						return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:#,###} {1}", decimal.Divide((decimal)bytes, max), order);
					return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:#,###.##} {1}", decimal.Divide((decimal)bytes, max), order);
				}
				max /= scale;
			}
			return "0 Bytes";

		}
	}
	#endregion

	#region PercentageConverter
	/// <summary>
	/// PercentageConverter converts a percentage value, in to a friendly such as 10% or 100%
	/// </summary>
	public class PercentageConverter : IValueConverter
	{
		#region IValueConverter Members
		/// <summary>
		/// Convert byte values to String Representation as byte, kb or gb
		/// </summary>
		/// <param name="value">The value to convert</param>
		/// <param name="targetType">The destination type</param>
		/// <param name="parameter">Optional and unused parameter</param>
		/// <param name="culture">Curernt Thread Culture</param>
		/// <returns>A string contains the size and size indicator as a string</returns>
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			string size = "{0} %";
			if (value != null)
				return string.Format(System.Globalization.CultureInfo.CurrentCulture, size, value);
			return string.Format(System.Globalization.CultureInfo.CurrentCulture, size, 0);
		}
		/// <summary>
		/// We only use one-way binding, so we don't implement this.
		/// </summary>
		/// <param name="value"></param>
		/// <param name="targetType"></param>
		/// <param name="parameter"></param>
		/// <param name="culture"></param>
		/// <returns></returns>
		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			throw new NotImplementedException();
		}
		#endregion
	}
	#endregion

	#region TransferRateConverter
	/// <summary>
	/// TransferRateConverter converts a TransferRate value, in to a friendly such as 2KB/s or 1MB/s
	/// </summary>
	public class TransferRateConverter : IValueConverter
	{
		#region IValueConverter Members
		/// <summary>
		/// Convert byte values to String Representation
		/// </summary>
		/// <param name="value">The value to convert</param>
		/// <param name="targetType">The destination type</param>
		/// <param name="parameter">Optional and unused parameter</param>
		/// <param name="culture">Curernt Thread Culture</param>
		/// <returns>A string contains the size and size indicator as a string</returns>
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			return ConvertToString((double)value);
		}
		/// <summary>
		/// We only use one-way binding, so we don't implement this.
		/// </summary>
		/// <param name="value"></param>
		/// <param name="targetType"></param>
		/// <param name="parameter"></param>
		/// <param name="culture"></param>
		/// <returns></returns>
		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			throw new NotImplementedException();
		}

		internal static string ConvertToString(double bytes)
		{
			if (double.IsInfinity(bytes))
				bytes = 0;
			const int scale = 1024;
			var orders = new string[] { "GB/s", "MB/s", "KB/s", "Bytes/s" };
			var max = (long)Math.Pow(scale, orders.Length - 1);

			foreach (var order in orders)
			{
				if (bytes > max)
				{
					if (bytes <= Math.Pow(scale, 2))
						return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:#,###} {1}", decimal.Divide((decimal)bytes, max), order);
					return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:#,###.##} {1}", decimal.Divide((decimal)bytes, max), order);
				}
				max /= scale;
			}
			return "0 Bytes";
		}
		#endregion
	}
	#endregion

	#region TimeConverter
	/// <summary>
	/// Converts a TimeSpan or Double to a Time String
	/// </summary>
	public class TimeConverter : IValueConverter
	{
		#region IValueConverter Members
		/// <summary>
		/// 
		/// </summary>
		/// <param name="value"></param>
		/// <param name="targetType"></param>
		/// <param name="parameter"></param>
		/// <param name="culture"></param>
		/// <returns></returns>
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			if (null != value)
			{
				if (value is double)
					return CovertToString((double)value);
				else if (value is TimeSpan)
					return CovertToString((TimeSpan)value);
				else
					return "0 sec";
			}
			return "0 sec";
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="value"></param>
		/// <param name="targetType"></param>
		/// <param name="parameter"></param>
		/// <param name="culture"></param>
		/// <returns></returns>
		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			throw new NotImplementedException();
		}

		internal static string CovertToString(double value)
		{
			var ts = TimeSpan.FromSeconds(value);
			return CovertToString(ts);
		}
		internal static string CovertToString(TimeSpan ts)
		{
			if (ts.Hours > 0)
				return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds);
			else if (ts.Minutes > 0)
				return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:00}:{1:00}", ts.Minutes, ts.Seconds);
			else
				return string.Format(System.Globalization.CultureInfo.CurrentCulture, "00:00:{0:00}", ts.TotalSeconds);
		}
		#endregion
	}
	#endregion
}